/*
 * Copyright 2010-2011 Marcin Blazejewski
 *
 * This file is part of Ground0.
 *
 * Ground0 is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Ground0 is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Ground0. If not, see <http://www.gnu.org/licenses/>.
 *
 */


#ifndef WORLD_H_
#define WORLD_H_

#include "eye.hpp"
#include "stuff.hpp"

#include <map>
#include <vector>
#include <string>

using namespace std;

static float ROTVEL_CAP = 130;
static float ROT_ACCEL = .1;
static int AUTO_HEADING_SCALE = 70;
static int AUTO_HEADING_LEVELS = 2;

static int BULLET_SPEED  = 400;
static int GUN_COOLDOWN = 50;

static int ASTEROIDS_N = 600;
static int ASTEROIDS_BASE_RADIUS = 500;
static int ASTEROIDS_SPAN = 700;
static int ASTEROIDS_SPEED = 20;
static int ASTEROIDS_CX = 500;
static int ASTEROIDS_CY= -50;
static int ASTEROIDS_CZ= 0;

static float AMBIENT_LIGHT  = 0.5;
static float DIFFUSE_LIGHT = 1.0;

#define SECSIZE 150             /**< Collision sector size. */

void load_rules(class Properties &config);

class Sim : public Stuff {
public:
    Vector                  thrust;
    float                   act[3]; // rotation actuators
    float rot_vel[3];
    
    float                   auto_heading;
    float                   auto_speed;
    int                     collision_recovery;

    Sim(Block *blueprint);
    //virtual ~Sim();

    virtual void tick(const float dt);

    // temp
    bool fire;
    int gun_cooldown;
    PartSet                 bullets;
};

#define R_SCALE         (1 << 0)
#define R_ORIENTATION   (1 << 1)
#define R_ROTATION      (1 << 2)
#define R_VELOCITY      (1 << 3)

class Asteroid : public Stuff {
private:
public:
    Asteroid(Stuff *blueprint);
    virtual ~Asteroid();

    void                      randomize(unsigned int f=~0);
};


#define N_STARS                        1000
#define N_ASTEROID_MODELS              4
class World : public BasicScene {
private:
    Camera                   *cam;
    list<Stuff*>              stuff;
    Sim                      *s1;
    Vector                    stars[N_STARS];

    /** 
     * Collision cache - groups objects into sectors based on their position.
     * Maps collision index to a list of Sim objects.<br>
     * index is ((cx << 16) | (cy << 8) | cz), where cx,cy,cz are sector indexes
     * in the 3 dimensions: cx = x / SECSIZE
     */
    map<int, list<Stuff*> >   cache; 
    
    /// asteroid blueprints
    Stuff                    *abp[N_ASTEROID_MODELS];
    Vector                    grav; // temporary grav center for asteroids

    void                      update_collision_cache(Stuff *s);
    //    void                      collide(Stuff *a, Vector &n);
    //void                      collide(Stuff *a, Stuff *b);
    void                      bullet_hit(Particle &bullet, Stuff *target);

    // recer
    vector<Stuff*>            gates;
    int                       next_gate;
    void                      generate_track();

protected:

public:
    World();
    virtual ~World();

    virtual void           tick(unsigned int ms);
    virtual void           render();

    void                   set_ship_model(Block *blueprint);
    Sim*                   get_ship() { return s1; };
    void                   set_camera_mode(int m);

    Stuff                    *get_next_gate();
};


#endif

